#ifndef __GRAPH_H__
#define __GRAPH_H__
#include "misc.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <list>
#include <map>
#include <string>
#include <algorithm>
#include <sstream>
#include <boost/config.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/topological_sort.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/graph/connected_components.hpp>		//find not connected components
#include <boost/graph/biconnected_components.hpp>	//find weak connected components
#include <boost/graph/subgraph.hpp>					//subgraph
#include <boost/graph/vertex_and_edge_range.hpp>  // edge_range function for parallel edges
#include <boost/graph/filtered_graph.hpp>
#include <boost/graph/graph_utility.hpp>
#include <boost/random.hpp>      //random num seq
#include <boost/tuple/tuple.hpp>  // for tuples ala std::pair
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/graph/kamada_kawai_spring_layout.hpp> //layout algorithm
#include <boost/graph/random_layout.hpp>
#include <boost/graph/circle_layout.hpp>
#include <boost/graph/fruchterman_reingold.hpp>
#include <iterator>
#include <utility>
#include <ginac/ginac.h>
#include <ginac/flags.h> // needed by is_a<T> funcs
//#include <combination.hpp>     // Internal combinator funcs
#include <xloops.h> //one loop analytic expressions
#include <sector_decomposition/sector_decomposition.h>
#include <boost/graph/isomorphism.hpp>

#include "field.h"
using namespace GiNaC;
using namespace boost;
using namespace xloops;
using std::cout;
using std::endl;
using std::string;
using std::setw;
using std::make_pair;
using std::pair;

//internal property for connected components calculation
namespace boost
{
  struct edge_component_t
  {
    enum
      { num = 555 };
    typedef edge_property_tag kind;
  };
  //edge_component;

  struct graph_num_t
  {
    enum
      { num = 999 };
    typedef graph_property_tag kind;
  };
  //graph_num;

  struct graph_factor_t
  {
    enum
      { num = 888 };
    typedef graph_property_tag kind;
  };
  //graph_factor;
}


// physical properties
struct vert
{
  ex gexpr;
  varidx gindex;
  std::string expr;
  bool external;

  //  field f1;        // vars for external
  //  field f2;        // leg fields
  //  field f3;        // for T-operation

  ///internal properties
  bool visited;   
  ex gmomentum;
  int type;
};

struct propagator
{
  ex gexpr;
  ex gmomentum;
  bool indexed;
  varidx to_index;
  varidx from_index;
  field to_field;
  field from_field;
  std::string expr;
  std::string momentum;
  int type;       //power of propagator 1 for spinors,0 for bosons and scalars
  int to_vertex;  //index of vertex it points to !!!!This indecies are GLOBAL vertex indecies!!!!!!!
  int from_vertex;//index of vertex it starts from
  bool visited;   //internal property
};


enum vertex_position_t { vertex_position };
namespace boost { BOOST_INSTALL_PROPERTY(vertex, position); }

// point (x,y) type for vertex layout
typedef square_topology<>::point_type point;


//addition internal graph properties
typedef property<vertex_index_t, std::size_t,property<vertex_position_t, point, vert> > vProperty;
typedef property<edge_index_t, std::size_t,property<edge_component_t, std::size_t,property<edge_weight_t, double, propagator> > > sProperty;
typedef property<graph_name_t, std::string,property<graph_num_t, std::size_t, property<graph_factor_t, std::string> > > gProperty;

// Graph type

typedef subgraph<adjacency_list<listS, vecS, undirectedS, 
  vProperty , sProperty , gProperty > > Graph;
//The list of subgraph's type

typedef boost::reference_wrapper<Graph> Graphref;
typedef std::list<Graphref> Graphref_lst;
//The list of graph product for substraction
typedef std::list<Graph> gLst;
// Pair type
typedef std::pair<std::size_t,std::size_t> Pair;
typedef std::vector<Graph> gVec;
// refernce to Graph::edge_descriptor to stor ein containers
typedef boost::reference_wrapper<Graph::edge_descriptor> edis_ref;

/// properies initialization, need review
static edge_component_t edge_component;
static graph_num_t graph_num;
static graph_factor_t graph_factor;

/// !!!!!!!!! NOT GRAPH but placed here!!!!!
/// Type of MAP for external lines info storage
typedef std::map<std::pair<unsigned int,unsigned int> ,std::list< std::pair< ex,field > > > map_ext_legs;
typedef std::map<unsigned int ,std::list< std::pair< ex,field >  > > dia_ext_legs;
typedef std::pair< ex,field > mom_field_pair;
/// !!!!!!!!! NOT GRAPH but placed here!!!!!
#endif // __GRAPH_H__
